# This python script takes the feature function code and the distance
# metric code and autogenerates a couple of C files to allow the
# functions to be selected run time.

import os, sys, string, re, glob, time


TYPELOOKUP = {"String":"CEXSPEC_TYPE_STR", "Int":"CEXSPEC_TYPE_INT"}

def get_cex_details(srcdir):
    feat_details = []
    files = glob.glob(srcdir + '/*.cc')
    for f in files:
        data = open(f).read()
        pat = re.match(".*?\n\s*(bool\s+CexFunc(String|Int)(\S+)\(.*?\))(.*)",
                       data, re.MULTILINE | re.DOTALL)
        while pat:
            print pat.group(3)
            data = pat.group(4)
            #function signature, pause handling, type, name
            feat_details.append([pat.group(1), pat.group(2), pat.group(3)])
            pat = re.match(".*?\n\s*(bool\s+CexFunc(String|Int)(\S+)\(.*?\))(.*)",
                           data, re.MULTILINE | re.DOTALL)
    return feat_details


def generate_cex_catalog_h(srcdir, feat_details):
    fp = open(os.path.join(srcdir, "cexfunctions.h"), 'w')
    cex_h_head = CEX_CATALOG_H_HEAD.replace("$TIME$", time.asctime())
    cex_h_head = cex_h_head.replace("$NO_FEATURES$", str(len(feat_details)))
    fp.write(cex_h_head)
    for feat in feat_details:
        fp.write(feat[0] + ";\n\n")
    fp.write(CEX_CATALOG_H_TAIL)
    fp.close()

def generate_cex_catalog_c(srcdir, feat_details):
    fp = open(os.path.join(srcdir, "cexfunctionscatalog.cc"), 'w')
    cex_h_head = CEX_CATALOG_C_HEAD.replace("$TIME$", time.asctime())
    fp.write(cex_h_head)

    fp.write(CEX_CATALOG_C_LINES["lbls"])
    for feat in feat_details[:-1]:
        fp.write('"' + feat[2] + '", ')
    fp.write('"' + feat_details[-1][2] + '"};\n\n')
    
    fp.write(CEX_CATALOG_C_LINES["funcs"])
    for feat in feat_details[:-1]:
        fp.write('&CexFunc' + feat[1] + feat[2] + ', ')
    fp.write('&CexFunc' + feat_details[-1][1]
             + feat_details[-1][2] + '};\n\n')

    fp.write(CEX_CATALOG_C_TYPEHELP)

    fp.write(CEX_CATALOG_C_LINES["type"])
    for feat in feat_details[:-1]:
        fp.write('' + TYPELOOKUP[feat[1]] + ', ')
    fp.write('' + TYPELOOKUP[feat_details[-1][1]] + '};\n\n')

    fp.write("}  // namespace kaldi\n")

CEX_CATALOG_H_HEAD = """// idlaktxp/cexfunctions.h

// Copyright 2013 CereProc Ltd.  (Author: Matthew Aylett)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.
//

// Automatically generated: $TIME$

#ifndef KALDI_IDLAKTXP_CEXFUNCTIONS_H
#define KALDI_IDLAKTXP_CEXFUNCTIONS_H

// This file autogenerated by running create_catalog.py
// Do not edit manually

#include "idlaktxp/txpcexspec.h"

namespace kaldi {

#define CEX_NO_FEATURES $NO_FEATURES$

"""


CEX_CATALOG_H_TAIL = """

}  // namespace kaldi

#endif  // KALDI_IDLAKTXP_CEXFUNCTIONS_H_
"""

CEX_CATALOG_C_HEAD = """// idlaktxp/cexfunctionscatalog.cc

// Copyright 2013 CereProc Ltd.  (Author: Matthew Aylett)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.
//

// Automatically generated: $TIME$

// This file autogenerated by running create_catalog.py
// Do not edit manually

#include "idlaktxp/txpcexspec.h"
#include "idlaktxp/cexfunctions.h"

namespace kaldi {

"""

CEX_CATALOG_C_TYPEHELP = """
// Return type
// Int - integer either a count or a class
// String - a string, part of a defined set of possible values listed in
//       cex-default.xml
"""

CEX_CATALOG_C_LINES = {"lbls":"const char* const CEXFUNCLBL[] = {", \
                      "funcs":"const cexfunction CEXFUNC[] = {", \
                      "pausehand":"const enum CEXSPECPAU_TYPE CEXFUNCPAUTYPE[] = {",\
                      "type":"const enum CEXSPEC_TYPE CEXFUNCTYPE[] = {",\
                           }


def main(argv=None):
    #get arguments
    if not argv:
        argv = sys.argv

    if len(argv) < 2 or  argv[1] == '-h':
        print "python create_framework <source dir>"
        print "\te.g. cd kaldi/src/idlakcex; python create_framework ."
        sys.exit(1)
    srcdir = argv[1]
    feat_details = get_cex_details(srcdir)
    if (len(feat_details) == 0):
        print "Error: No feature code found\n"
        sys.exit(1)
    generate_cex_catalog_h(srcdir, feat_details) 
    generate_cex_catalog_c(srcdir, feat_details) 

    sys.exit(0)


if __name__ == "__main__":
    sys.exit(main())
